package com.icinfo.cloud.provider.punish.common.seal.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.icinfo.cloud.common.core.page.PageResponse;
import com.icinfo.cloud.common.security.util.UserUtil;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.enums.AttachmentRequestContentTypeEnum;
import com.icinfo.cloud.provider.common.enums.FileTransferFormEnum;
import com.icinfo.cloud.provider.common.enums.YesOrNoEnum;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.common.utils.Base64ToMultipartFileUtil;
import com.icinfo.cloud.provider.common.utils.FileUtil;
import com.icinfo.cloud.provider.common.utils.SpringContextUtil;
import com.icinfo.cloud.provider.punish.common.caseregister.service.IRegisterCommonService;
import com.icinfo.cloud.provider.punish.common.seal.dto.BindSealPageDto;
import com.icinfo.cloud.provider.punish.common.seal.dto.FileSealInfoQueryDto;
import com.icinfo.cloud.provider.punish.common.seal.service.IFileSealProvinceUnifiedService;
import com.icinfo.cloud.provider.punish.common.seal.utils.ChongQingSignUtil;
import com.icinfo.cloud.provider.punish.common.seal.vo.BindSealVo;
import com.icinfo.cloud.provider.punish.common.seal.vo.ConfigOrgRelatedSealVo;
import com.icinfo.cloud.provider.punish.config.service.IConfigOrgRelatedSealService;
import com.icinfo.cloud.xzcf.provider.member.org.dto.Org;
import com.icinfo.cloud.xzcf.provider.member.userinfo.dto.UserDTO;
import com.icinfo.framework.tools.utils.StringUtils;
import com.timevale.tgtext.text.pdf.PdfReader;
import com.timvale.sealplatform.bean.PosBean;
import com.timvale.sealplatform.sdk.ClientManageService;
import com.timvale.sealplatform.sdk.config.HttpConnectionConfig;
import com.timvale.sealplatform.sdk.config.ProjectConfig;
import com.timvale.sealplatform.sdk.file.SignLocalClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 描述：文件签章接口实现类（省统）
 *
 * @author xiangyuyu
 * @date 2022-07-08 15:30
 */
@Service
@Slf4j
public class FileSealProvinceUnifiedServiceImpl implements IFileSealProvinceUnifiedService {
    private static SignLocalClient signLocalClient;

    /*@Value("${environ}")
    private String environ;*/
    static {
        ProjectConfig projectConfig = new ProjectConfig();
        //todo 先写死
        projectConfig.setAppId("330000453");
        projectConfig.setSecret("be503d15b62345989849c10ec76edcc0");
        //本地使用
        //projectConfig.setDomainName("223.4.78.65:9999");
        //projectConfig.setDomainName("zjyz.zjzwfw.gov.cn:9999");

        projectConfig.setDomainName("10.145.147.112:8581/proxy/dzyzAddr/");
        HttpConnectionConfig httpConnectionConfig = new HttpConnectionConfig();
        httpConnectionConfig.setProtocol("http");
        httpConnectionConfig.setConnectionTimeOut(3000);
        signLocalClient = ClientManageService.initClient(projectConfig, httpConnectionConfig);
    }

    @Resource
    private IConfigOrgRelatedSealService configOrgRelatedSealService;
    @Resource
    private IRegisterCommonService commonService;
    @Value("${document.url}")
    private String url;
    @Value("${document.api.uploadBase64File}")
    private String uploadBase64File;

    /**
     * 【V1.3.1】描述：获取签章后的文件(省统)
     *
     * @param queryDto {@link FileSealInfoQueryDto}
     * @return Map<String, Object> 签章结果信息("errorMsg"-错误信息【String】/"fileBytes"-签章完成的文件字节数组【byte[]】)
     * @author XiangYuYu
     * @date 2021/11/08
     */
    @Override
    public Map<String, Object> getFileAfterSeal(FileSealInfoQueryDto queryDto) {
        LocalDateTime startTime = LocalDateTime.now();
        log.info("getFileAfterSeal start...startTime:{}", startTime);
        String uniscid = queryDto.getUniscid();
        if (StringUtils.isBlank(uniscid)) {
            //获取机构统一社会信用代码
            UserDTO userInfo = UserUtil.getUserInfo();
            if (ObjectUtils.isEmpty(userInfo)) {
                throw new BusinessException("登录失效");
            }
            Org orgInfo = commonService.getUserOrgMsg();
            uniscid = orgInfo.getUniCode();
            if (StringUtils.isBlank(uniscid)) {
                uniscid = userInfo.getUnicode();
            }
        }
        String sealCode = Constant.STRING_HORIZONTAL_BARS;
        if (!SpringContextUtil.checkIsPrdProfile()) {
            ConfigOrgRelatedSealVo tmpSealConfigInfo = configOrgRelatedSealService.getOrgRelatedSealConfigInfo("331005000M020N9999", "");
            if (!ObjectUtils.isEmpty(tmpSealConfigInfo)) {
                sealCode = tmpSealConfigInfo.getSealCode();
            }
        }
        if (YesOrNoEnum.YES.getCode().equals(queryDto.getIsSealPreview())) {
            if (!ObjectUtils.isEmpty(queryDto.getSealCode())) {
                sealCode = queryDto.getSealCode();
            } else {
                throw new BusinessException("印章预览时请指定印章编码");
            }
        } else {
            if (SpringContextUtil.checkIsPrdProfile()) {
                if (ObjectUtils.isEmpty(uniscid)) {
                    throw new BusinessException("无统一社会信用代码");
                } else {
                    log.info("统一信用代码:{},deptCode,{},", uniscid, queryDto.getDeptCode());
                    ConfigOrgRelatedSealVo configOrgRelatedSeal = configOrgRelatedSealService.getOrgRelatedSealConfigInfo(uniscid, queryDto.getDeptCode());
                    sealCode = configOrgRelatedSeal.getSealCode();
                    if (ObjectUtils.isEmpty(configOrgRelatedSeal) || ObjectUtils.isEmpty(sealCode)) {
                        throw new BusinessException("未匹配到印章编码信息，请联系部门管理员确认“单位参数配置“中印章编码是否正确。");
                    }
                }
            }
        }

        List<File> waitToDelFiles = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>(2);
        //参数校验
        String errorMsg = fileSealInfoValidated(queryDto);
        if (!ObjectUtils.isEmpty(errorMsg)) {
            log.warn(errorMsg);
            resultMap.put("errorMsg", errorMsg);
            resultMap.put("fileBytes", null);
            return resultMap;
        }
//        Map<String, Object> posMap = assemblePosBean(queryDto);
//        PosBean posBean = (PosBean) posMap.get("posBean");
//        int signType = (int) posMap.get("signType");
//        String password = ObjectUtils.isEmpty(queryDto.getPwdB64()) ? "" : queryDto.getPwdB64();
//        SignPDFResult signPdfResult;
        byte[] desFileBuffer = null;
        String dir = "pdfFiles";
        try {
            //走对应的签章渠道
            MultipartFile multipartFile;
            if (FileTransferFormEnum.FILE_TRANSFER_FORM_1.getCode().equalsIgnoreCase(queryDto.getFileTransferForm())) {
                String base64string = queryDto.getFileBase64();
                multipartFile = new Base64ToMultipartFileUtil(base64string, "data:application/pdf;base64,");
            } else {
                multipartFile = queryDto.getFile();
            }
            File oriFile = null;
            if (!"".equals(multipartFile) && multipartFile.getSize() > 0) {
                InputStream ins = multipartFile.getInputStream();
                oriFile = new File(multipartFile.getOriginalFilename());
                FileUtil.inputStreamToFile(ins, oriFile);
                ins.close();
                //pdf临时生成目录
                File fileMkd = new File(dir);
                if (!fileMkd.exists()) {
                    fileMkd.mkdirs();
                }
            }
            if (SpringContextUtil.checkIsDevProfile()) {
                desFileBuffer = ChongQingSignUtil.getSignFileByte(oriFile, "5ec0d01dbef92dc73e8010dc7800a8c3aae6480a2a40eb76f5fb8c963b3f31e61053afd3cd355003b707a88e351aa3ac");
            } else {
                desFileBuffer = ChongQingSignUtil.getSignFileByte(oriFile, sealCode);
            }
//            String fileName = oriFile.getName();
//            String desFilePath = dir + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + fileName;
//            //SignLocalClient signLocalClient = getSignLocalClient();
//            log.info("getSignLocalClient end time:{}:{}", LocalDateTime.now(),"sealCode+++++++++++++++++++++++++"+sealCode);
//            //signPdfResult = signLocalClient.localSignPDF(oriFile.getAbsolutePath(), desFilePath, sealCode, signType, posBean, password);
//            signPdfResult = SignLocalClientUtil.getClient().localSignPDF(oriFile.getAbsolutePath(), desFilePath, sealCode, signType, posBean, password);
//            log.info("localSignPDF end time:{}:{}", LocalDateTime.now(),"pdf:" + signPdfResult);
//            if (ObjectUtils.isEmpty(signPdfResult)) {
//                errorMsg = "签章失败-signPDFResult：返回值为null";
//                log.warn(errorMsg);
//            } else {
//                int errCode = signPdfResult.getErrCode();
//                if (!ObjectUtils.isEmpty(errCode) && !Constant.INTEGER_0.equals(errCode)) {
//                    if(4023==signPdfResult.getErrCode()){
//                        errorMsg = "印章过期或已失效，请尽快操作印章申请或延期，具体操作请点击查看《党政机关电子印章操作指南》，或在浙政钉咨询服务群进行咨询。";
//                    }else {
//                        errorMsg = "印章未授权，请联系部门印章管理员在“浙江省统一电子印章接入平台”授权给“浙江省统一行政处罚办案系统”使用。具体操作请点击查看《党政机关电子印章操作指南》";
//                    }
//                    log.warn(errorMsg);
//                }
//            }
//            FileInputStream fis = new FileInputStream(desFilePath);
//            desFileBuffer = FileUtil.InputStreamToByte(fis);
//            waitToDelFiles.add(oriFile);
//            waitToDelFiles.add(new File(desFilePath));
//            delRedundancyFile(waitToDelFiles);
            resultMap.put("fileBytes", desFileBuffer);
            resultMap.put("errorMsg", errorMsg);
            /*if (!"N".equals(environ)) {
                resultMap.put("errorMsg", errorMsg);
            }*/
        } catch (ArrayIndexOutOfBoundsException e) {
            errorMsg = "请输入完整的base64信息";
            log.warn(errorMsg + e.getMessage());
            /*if ("N".equals(environ)) {
                return resultMap;
            }*/
            resultMap.put("fileBytes", desFileBuffer);
            resultMap.put("errorMsg", errorMsg);
            return resultMap;
        } catch (Exception e) {
            errorMsg = ObjectUtils.isEmpty(errorMsg) ? "签章失败：" + e.getMessage() : errorMsg;
            log.warn(errorMsg + e.getMessage(), e);
            /*if ("N".equals(environ)) {
                return resultMap;
            }*/
            resultMap.put("fileBytes", desFileBuffer);
            resultMap.put("errorMsg", errorMsg);
            return resultMap;
        }
        LocalDateTime endTime = LocalDateTime.now();
        Duration duration = Duration.between(startTime, endTime);
        log.info("getFileAfterSeal end endTime::{},timeConsume:{}", endTime, duration.toMillis());
        return resultMap;
    }

    /**
     * 【V1.0.0】描述：获取签章后的文件[仅支持base64]
     *
     * @param queryDto 文件签章信息查询数据传输对象
     * @return Map<String, Object> 签章结果信息("errorMsg"-错误信息【String】/"fileBytes"-签章完成的文件字节数组【byte[]】)
     * @author XiangYuYu
     * @date 2021/11/08
     */
    public Map<String, Object> getFileAfterSignForBase64(FileSealInfoQueryDto queryDto) {
        queryDto.setFileTransferForm(Constant.STRING_1);
        return getFileAfterSeal(queryDto);
    }


    /**
     * 描述：文件签章信息查询数据传输对象数据合法性校验【目前仅支持指定pdf文件签章】
     *
     * @param queryDto {@link FileSealInfoQueryDto}
     * @return String 错误信息
     * @author xiangyuyu
     * @date 2022-07-08 16:42
     */
    private String fileSealInfoValidated(FileSealInfoQueryDto queryDto) {
        String errorMsg = "";
        try {
            String sealCode = queryDto.getSealCode();
            if (ObjectUtils.isEmpty(sealCode)) {
                errorMsg = "请指定印章编码";
                return errorMsg;
            }
            String fileType = queryDto.getFileType();
            String fileTransferForm = queryDto.getFileTransferForm();
            if (!FileTransferFormEnum.isLegalEnumCode(fileTransferForm)) {
                errorMsg = "请指定签章文件传输形式（1-base64/2-文件对象）";
                return errorMsg;
            } else {
                if (FileTransferFormEnum.FILE_TRANSFER_FORM_1.getCode().equalsIgnoreCase(fileTransferForm)
                        && ObjectUtils.isEmpty(queryDto.getFileBase64())) {
                    errorMsg = "请指定需要签章的base64信息";
                    return errorMsg;
                }
                MultipartFile file = queryDto.getFile();
                if (FileTransferFormEnum.FILE_TRANSFER_FORM_2.getCode().equalsIgnoreCase(fileTransferForm)) {
                    if (ObjectUtils.isEmpty(file)) {
                        errorMsg = "请指定需要签章的文件";
                        return errorMsg;
                    }
                    if (ObjectUtils.isEmpty(fileType)) {
                        errorMsg = "请指定需要签章的文件类型";
                        return errorMsg;
                    }
                    if (AttachmentRequestContentTypeEnum.pdf.getCode().equalsIgnoreCase(fileType)) {
                        String fileFullName = file.getOriginalFilename();
                        if (log.isDebugEnabled()) {
                            log.debug("fileFullName:" + fileFullName);
                        }
                        String suffix = fileFullName.substring(fileFullName.lastIndexOf(Constant.STRING_POINT) + 1);
                        if (!AttachmentRequestContentTypeEnum.pdf.getCode().equalsIgnoreCase(suffix)) {
                            errorMsg = "文件后缀名与文件类型不匹配(" + "fileType:" + fileType + ",文件后缀名：" + suffix + ")";
                            return errorMsg;
                        }
                    } else {
                        errorMsg = "签章的文件类型必须为pdf";
                        return errorMsg;
                    }
                }
            }
        } catch (Exception e) {
            errorMsg = "文件签章信息查询数据传输对象数据合法性校验时出现异常：" + e.getMessage();
        }
        return errorMsg;
    }


    /**
     * 描述：文件签章并上传到oss
     *
     * @param queryDto FileSealInfoQueryDto
     * @return String 签章后的文件信息
     * @author xiangyuyu
     * @date 2022-07-08 15:26
     */
    @Override
    public String dealFileSeal(FileSealInfoQueryDto queryDto) {
        queryDto.setFileType("pdf");
        queryDto.setFileTransferForm("1");
        queryDto.setFileBase64(queryDto.getFileBase64());
        queryDto.setAddSignTime(false);
        queryDto.setSealCode("");
        queryDto.setKey("签章处");
        queryDto.setSignType(4);
        queryDto.setSealCode("12");
        queryDto.setPosX(0);
        queryDto.setPosY(-15);
        //签章
        Map<String, Object> fileAfterSeal = getFileAfterSeal(queryDto);
        if (ObjectUtil.isNotEmpty(fileAfterSeal.get("errorMsg"))) {
            log.info("warn fileSealService,result:{}", fileAfterSeal.get("errorMsg"));
            throw new BusinessException(Constant.SEAL_ERROR_MESSAGE);
        }
        //获取pdf页码若2张以上，加盖骑缝章
        try {
            byte[] fileBytes = (byte[]) fileAfterSeal.get("fileBytes");
            InputStream ins = new ByteArrayInputStream(fileBytes);
            PdfReader pdfReader = new PdfReader(ins);
            int pages = pdfReader.getNumberOfPages();
            if (pages > 1) {
                queryDto.setFileType("pdf");
                queryDto.setFileTransferForm("1");
                String base64 = Base64.encodeBase64String(fileBytes);
                queryDto.setFileBase64(base64);
                queryDto.setKey("");
                queryDto.setSealCode("21");
                queryDto.setSignType(3);
                queryDto.setPosX(100);
                queryDto.setPosY(450);
                queryDto.setPosPage("1-" + pages);
                fileAfterSeal = getFileAfterSeal(queryDto);
                if (ObjectUtil.isNotEmpty(fileAfterSeal.get("errorMsg"))) {
                    log.info("warn fileSealService,result:{}", fileAfterSeal.get("errorMsg"));
                    throw new BusinessException(Constant.SEAL_ERROR_MESSAGE);
                }
            }
        } catch (IOException e) {
            throw new BusinessException("系统异常:" + e.getMessage());
        }
        //上传签章后的文件到oss
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("fileBytes", fileAfterSeal.get("fileBytes"));
        jsonObject.put("fileType", "pdf");
        jsonObject.put("fileName", "");
        JSONObject parseObject = JSON.parseObject(HttpUtil.post(url + uploadBase64File, jsonObject.toString()));
        String cd = "code";
        int th = 200;
        if (parseObject.getInteger(cd) == th) {
            String url = parseObject.getJSONObject("data").getString("ossUrl");
            //log.info("签章后地址：{}", url);
            return url;
        } else {
            log.info("warn receive sign file upload oss fail,result:{}", parseObject.toString());
            throw new BusinessException("签章后上传文件失败：" + jsonObject.getString("message"));
        }
    }

    @Override
    public Map<String, Object> getFileAfterSealAuto(FileSealInfoQueryDto queryDto) {
       return getFileAfterSeal(queryDto);
    }

    @Override
    public PageResponse<BindSealVo> getBindSealPage(BindSealPageDto dto) {
        if (Objects.isNull(dto.getCardNo()) && Objects.isNull(dto.getUsci())) {
            throw new BusinessException("证件号与统一社会信用代码不能同时为空");
        }
        return ChongQingSignUtil.getBindSealPage(dto);
    }

    /**
     * 描述：删除冗余文件
     *
     * @param redundancyFiles 冗余文件
     * @author xiangyuyu
     * @date 2021-11-24 20:04
     */
    private void delRedundancyFile(List<File> redundancyFiles) {
        redundancyFiles.forEach(e -> {
            if (e.exists()) {
                e.delete();
            }
        });
    }

    /**
     * 描述：组装签章请求入参
     *
     * @param queryDto 文件签章信息查询数据传输对象
     * @return Map<String, Object> 签章请求入参
     * @author xiangyuyu
     * @date 2021-11-12 17:30
     */
    private Map<String, Object> assemblePosBean(FileSealInfoQueryDto queryDto) {
        Map<String, Object> map = new HashMap<>(2);
        PosBean posBean = new PosBean();
        posBean.setPosX(ObjectUtils.isEmpty(queryDto.getPosX()) ? 0 : queryDto.getPosX());
        posBean.setPosY(ObjectUtils.isEmpty(queryDto.getPosY()) ? 0 : queryDto.getPosY());
        Integer signType = ObjectUtils.isEmpty(queryDto.getSignType()) ? Constant.INTEGER_4 : queryDto.getSignType();
        String key = queryDto.getKey();
        if (!ObjectUtils.isEmpty(key)) {
            posBean.setPosPage("");
            signType = Constant.INTEGER_4;
        } else {
            posBean.setPosPage(ObjectUtils.isEmpty(queryDto.getPosPage()) ? Constant.STRING_1 : queryDto.getPosPage());
            key = "签章处";
        }
        posBean.setKey(key);
        posBean.setKeyIndex(ObjectUtils.isEmpty(queryDto.getKeyIndex()) ? 0 : queryDto.getKeyIndex());
        posBean.setAddSignTime(ObjectUtils.isEmpty(queryDto.getAddSignTime()) ? false : queryDto.getAddSignTime());
        map.put("signType", signType);
        map.put("posBean", posBean);
        return map;
    }


    /**
     * 描述：文件签章信息查询数据传输对象数据合法性校验【目前仅支持指定pdf文件签章】
     *
     * @param queryDto 文件签章信息查询数据传输对象
     * @return String 错误信息
     * @author XiangYuYu
     * @date 2021/11/09
     */
    private String fileSealInfoValidatedProvinceUnified(FileSealInfoQueryDto queryDto) {
        String errorMsg = "";
        try {
            String sealCode = queryDto.getSealCode();
            if (ObjectUtils.isEmpty(sealCode)) {
                errorMsg = "请指定印章编码";
                return errorMsg;
            }
            String fileType = queryDto.getFileType();
            String fileTransferForm = queryDto.getFileTransferForm();
            if (!FileTransferFormEnum.isLegalEnumCode(fileTransferForm)) {
                errorMsg = "请指定签章文件传输形式（1-base64/2-文件对象）";
                return errorMsg;
            } else {
                if (FileTransferFormEnum.FILE_TRANSFER_FORM_1.getCode().equalsIgnoreCase(fileTransferForm)
                        && ObjectUtils.isEmpty(queryDto.getFileBase64())) {
                    errorMsg = "请指定需要签章的base64信息";
                    return errorMsg;
                }
                MultipartFile file = queryDto.getFile();
                if (FileTransferFormEnum.FILE_TRANSFER_FORM_2.getCode().equalsIgnoreCase(fileTransferForm)) {
                    if (ObjectUtils.isEmpty(file)) {
                        errorMsg = "请指定需要签章的文件";
                        return errorMsg;
                    }
                    if (ObjectUtils.isEmpty(fileType)) {
                        errorMsg = "请指定需要签章的文件类型";
                        return errorMsg;
                    }
                    if (AttachmentRequestContentTypeEnum.pdf.getCode().equalsIgnoreCase(fileType)) {
                        String fileFullName = file.getOriginalFilename();
                        log.info("fileFullName:" + fileFullName);
                        String suffix = fileFullName.substring(fileFullName.lastIndexOf(Constant.STRING_POINT) + 1);
                        if (!AttachmentRequestContentTypeEnum.pdf.getCode().equalsIgnoreCase(suffix)) {
                            errorMsg = "文件后缀名与文件类型不匹配(" + "fileType:" + fileType + ",文件后缀名：" + suffix + ")";
                            return errorMsg;
                        }
                    } else {
                        errorMsg = "签章的文件类型必须为pdf";
                        return errorMsg;
                    }

                }
            }
        } catch (Exception e) {
            errorMsg = "文件签章信息查询数据传输对象数据合法性校验时出现异常：" + e.getMessage();
            log.warn(errorMsg);
        }
        return errorMsg;
    }

    /**
     * 描述：获取本地签章客户端
     *
     * @return 本地签章客户端
     * @author XiangYuYu
     * @date 2021/11/08
     */
    /*public SignLocalClient getSignLocalClient() {
        ProjectConfig projectConfig = new ProjectConfig();
        projectConfig.setAppId(appId);
        projectConfig.setSecret(secret);
        projectConfig.setDomainName(signUrl);
        HttpConnectionConfig httpConnectionConfig = new HttpConnectionConfig();
        httpConnectionConfig.setProtocol(protocol);
        httpConnectionConfig.setConnectionTimeOut(timeoutLimit);
        return ClientManageService.initClient(projectConfig, httpConnectionConfig);
    }*/


}
